package com.gopay.checkorder.service.impl;

import java.math.BigDecimal;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.checkorder.service.BankOrderService;
import com.gopay.checkorder.service.task.BankCountDownLatch;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.BisBankInterfaceChannel;
import com.gopay.common.constants.bank.BocConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.boc.ebank.BocB2bMessage;
import com.gopay.common.domain.bank.dayend.BaseDayendEntry;
import com.gopay.common.domain.cashier.BankCardType;
import com.gopay.common.domain.cps.vo.CheckOrderResult;
import com.gopay.common.domain.cps.vo.InAccInfo;
import com.gopay.remote.bank.BankInteractRemoteService;

/**
 * @CheckOrderBocB2bImpl.java
 * @author wanggang
 * @2013-11-12 下午2:37:38 www.gopay.com.cn Inc.All rights reserved.
 */
public class CheckOrderBocB2bImpl implements BankOrderService {

	private final static Logger logger = LoggerFactory.getLogger("BOC");

	@Resource(name = "bankClient")
	private BankInteractRemoteService bankClient;
	@Override
	public CheckOrderResult checkOrder(BankOrder bankOrder, String target) {
		CheckOrderResult checkOrderResult = new CheckOrderResult();
		checkOrderResult.setSuccess(false);
		checkOrderResult.setOrderId(bankOrder.getOrderId());
		try {
			BocB2bMessage base = new BocB2bMessage();
			base.setOrderId(bankOrder.getOrderId());
			base.setBankOrderId(bankOrder.getOutOrderId());
			base.setBank(BankConstants.BANK_LOGO_BOC);
			base.setBankIntrChann(BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode()));
			base.setBankBusProd(BisBankBusinessProd.get(bankOrder.getBankBizProdCode()));
			Result result = new Result();
			result = bankClient.query(base);
			if (result == null || !result.isSuccess()) {
				logger.debug("bankClient fail.");
				
				if(result ==null || ProcCodeConstants.PROC_CODE_100E6037.equals(result.getResultCode())){
					BankCountDownLatch.failIncrease(bankOrder.getBankCode());
					checkOrderResult.setCommunicateError(true);
				}
				
				logger.debug(ToStringBuilder.reflectionToString(result,ToStringStyle.DEFAULT_STYLE));
				checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
				checkOrderResult.setErrMsg("系统返回对账结果为空");
				return checkOrderResult;
			}
			// header不为空时，中行回应有错误码（错误信息）--对账查询失败，不作处理
			BocB2bMessage res = (BocB2bMessage) result.getDefaultModel();
			if (res == null) {
				// 查询订单为空
				logger.debug("fail:orderId:" + bankOrder.getOrderId()+ " errcode:" + ProcCodeConstants.PROC_CODE_100E5062+ " err:bis query is null.");
				checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5062);
				checkOrderResult.setErrMsg("银行返回对账结果为空");
			}

			if (StringUtils.isNotBlank(res.getRtnCode()) && !"00".equals(res.getRtnCode())) {
				// 查询订单错误
				logger.debug("fail:orderId:" + bankOrder.getOrderId()+ " errcode:" + res.getRtnCode() + " err:"+ res.getRtnMsg());
				checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5062);
				checkOrderResult.setErrMsg(res.getRtnMsg());
				return checkOrderResult;
			}
			// 中行返回结果数据集，我平台一次只查一笔
			List<BocB2bMessage> bocB2bMessageList = res.getList();
			if (bocB2bMessageList != null && bocB2bMessageList.size() > 0) {
				BocB2bMessage orderRes = (BocB2bMessage) res.getList().get(0);
				checkOrderResult.setOrderId(orderRes.getOrderNo());
				checkOrderResult.setAmount(new BigDecimal(orderRes.getOrderAmount()));
				// 如果订单状态：支付成功
				if (StringUtils.equals(BocConstants.B2B_ORDER_STATUS_SUCCESS,orderRes.getOrderStatus())) {
					logger.info("中行B2B订单" + orderRes.getOrderNo() + "交易返回成功("+ orderRes.getOrderStatus() + ")，执行账务处理");
					checkOrderResult.setSuccess(true);
					InAccInfo accInfo = new InAccInfo();
					accInfo.setOrderId(bankOrder.getOrderId());
					accInfo.setAmount(new BigDecimal(orderRes.getOrderAmount()));
					accInfo.setRetCode("00");
					accInfo.setCardType(BankCardType.Unknown.toString());
					checkOrderResult.setAccInfo(accInfo);
					/* 以下两个状态，视为订单失败，系统将进行失败账务处理。 */
				} else if (StringUtils.equals(BocConstants.B2B_ORDER_STATUS_EXPIRE,orderRes.getOrderStatus())) {
					//失败处理
     				checkOrderResult.setBankFailure(true);
					logger.info("中行B2B订单" + orderRes.getOrderNo()+ "交易返回信息为：过期失效，返回码：(" + orderRes.getOrderStatus()+ ")，执行失败处理");
					checkOrderResult.setErrMsg("过期失效");
				} else if (StringUtils.equals(BocConstants.B2B_ORDER_STATUS_FAIL,orderRes.getOrderStatus())) {
					//失败处理
     				checkOrderResult.setBankFailure(true);
					logger.info("中行B2B订单" + orderRes.getOrderNo()+ "交易返回信息为：交易失败，返回码：(" + orderRes.getOrderStatus()+ ")，执行失败处理");
					checkOrderResult.setErrMsg("交易失败");
					/* 以下为中间状态，订单状态不改变 */
				} else if (StringUtils.equals(BocConstants.B2B_ORDER_STATUS_EXCEPTION,orderRes.getOrderStatus())) {
					logger.info("中行B2B订单" + orderRes.getOrderNo()+ "交易返回信息为：支付异常，暂不进行账务处理，返回码："+ orderRes.getOrderStatus());
					checkOrderResult.setErrMsg("支付异常");
				} else if (StringUtils.equals(BocConstants.B2B_ORDER_STATUS_UNCOMFIRM,orderRes.getOrderStatus())) {
					logger.info("中行B2B订单" + orderRes.getOrderNo()+ "交易返回信息为：支付未确认，暂不进行账务处理，返回码："+ orderRes.getOrderStatus());
					checkOrderResult.setErrMsg("支付未确认");
				} else if (StringUtils.equals(BocConstants.B2B_ORDER_STATUS_COMFIRM,orderRes.getOrderStatus())) {
					logger.info("中行B2B订单" + orderRes.getOrderNo()+ "交易返回信息为：支付确认，暂不进行账务处理，返回码："+ orderRes.getOrderStatus());
					checkOrderResult.setErrMsg("支付确认");
				} else {
					// 银行订单状态未明确
					logger.debug("中行B2B订单" + orderRes.getOrderNo() + "交易结果未明确("+ orderRes.getOrderStatus() + ")，跳过");
					checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5062);
					checkOrderResult.setErrMsg("交易结果未明确");
				}
			}
			return checkOrderResult;
		} catch (Exception e) {
			logger.debug("bankClient fail.", e);
			checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
			checkOrderResult.setErrMsg("对账调用bis失败");
			return checkOrderResult;
		}
	}
	@Override
	public BankOrder getDbOrder() {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public BaseMessage dayend(String bank_bus) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public List<CheckOrderResult> checkDayend(String bank_bus) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public Result getDayendMsg(String string) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public CheckOrderResult checkDayendOrder(BaseDayendEntry bdm, BankOrder bo) {
		// TODO Auto-generated method stub
		return null;
	}
}
